package org.example.task;

import org.example.service.AccessStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Set;

/**
 * 数据清理和同步定时任务
 * 
 * @author Your Name
 * @since 2024-07-01
 */
@Component
public class DataCleanupTask {
    
    @Autowired
    private AccessStatisticsService accessStatisticsService;
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    // Redis key前缀
    private static final String REDIS_ACCESS_COUNT_PREFIX = "access_count:";
    private static final String REDIS_DAILY_COUNT_PREFIX = "daily_count:";
    private static final String REDIS_HOURLY_COUNT_PREFIX = "hourly_count:";
    private static final String REDIS_UNIQUE_IP_PREFIX = "unique_ip:";
    
    /**
     * 每天凌晨2点执行数据清理
     * 清理30天前的访问统计数据
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void cleanExpiredData() {
        try {
            System.out.println("开始执行数据清理任务...");
            
            // 清理30天前的访问统计数据
            accessStatisticsService.cleanExpiredData(30);
            
            System.out.println("数据清理任务执行完成");
        } catch (Exception e) {
            System.err.println("数据清理任务执行失败: " + e.getMessage());
        }
    }
    
    /**
     * 每小时执行一次Redis数据同步到数据库
     * 将Redis中的统计数据批量同步到数据库，确保数据持久化
     */
    @Scheduled(fixedRate = 3600000) // 1小时 = 3600000毫秒
    public void syncRedisDataToDatabase() {
        try {
            System.out.println("开始执行Redis数据同步任务...");
            
            // 调用访问统计服务的批量保存方法
            accessStatisticsService.batchSaveToDatabase();
            
            System.out.println("Redis数据同步任务执行完成");
        } catch (Exception e) {
            System.err.println("Redis数据同步任务执行失败: " + e.getMessage());
        }
    }
    
    /**
     * 每天凌晨3点执行Redis数据清理
     * 清理过期的Redis缓存数据，释放内存空间
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void cleanExpiredRedisData() {
        try {
            System.out.println("开始执行Redis数据清理任务...");
            
            // 清理过期的访问记录缓存
            cleanExpiredAccessRecords();
            
            // 清理过期的统计缓存
            cleanExpiredStatisticsCache();
            
            System.out.println("Redis数据清理任务执行完成");
        } catch (Exception e) {
            System.err.println("Redis数据清理任务执行失败: " + e.getMessage());
        }
    }
    
    /**
     * 清理过期的访问记录缓存
     */
    private void cleanExpiredAccessRecords() {
        try {
            // 这里可以添加清理过期访问记录的逻辑
            // 由于Redis会自动过期，这里主要是清理一些异常数据
            System.out.println("清理过期访问记录缓存完成");
        } catch (Exception e) {
            System.err.println("清理过期访问记录缓存失败: " + e.getMessage());
        }
    }
    
    /**
     * 清理过期的统计缓存
     */
    private void cleanExpiredStatisticsCache() {
        try {
            // 清理7天前的日统计缓存
            String sevenDaysAgo = LocalDateTime.now().minusDays(7).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            
            // 获取所有日统计的key
            Set<String> dailyKeys = redisTemplate.keys(REDIS_DAILY_COUNT_PREFIX + "*");
            if (dailyKeys != null) {
                for (String key : dailyKeys) {
                    // 检查key中的日期是否过期
                    if (key.contains(sevenDaysAgo)) {
                        redisTemplate.delete(key);
                        System.out.println("删除过期日统计缓存: " + key);
                    }
                }
            }
            
            // 清理48小时前的小时统计缓存
            String twoDaysAgo = LocalDateTime.now().minusHours(48).format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH"));
            
            // 获取所有小时统计的key
            Set<String> hourlyKeys = redisTemplate.keys(REDIS_HOURLY_COUNT_PREFIX + "*");
            if (hourlyKeys != null) {
                for (String key : hourlyKeys) {
                    // 检查key中的时间是否过期
                    if (key.contains(twoDaysAgo)) {
                        redisTemplate.delete(key);
                        System.out.println("删除过期小时统计缓存: " + key);
                    }
                }
            }
            
            System.out.println("清理过期统计缓存完成");
        } catch (Exception e) {
            System.err.println("清理过期统计缓存失败: " + e.getMessage());
        }
    }
    
    /**
     * 每5分钟执行一次内存缓存同步
     * 将内存缓存中的数据同步到Redis，确保数据一致性
     */
    @Scheduled(fixedRate = 300000) // 5分钟 = 300000毫秒
    public void syncMemoryCacheToRedis() {
        try {
            System.out.println("开始执行内存缓存同步任务...");
            
            // 这里可以添加内存缓存同步到Redis的逻辑
            // 由于AccessStatisticsServiceImpl中已经有内存缓存同步机制，
            // 这里主要是作为额外的保障
            
            System.out.println("内存缓存同步任务执行完成");
        } catch (Exception e) {
            System.err.println("内存缓存同步任务执行失败: " + e.getMessage());
        }
    }
}
